<template>
  <NvForm
    ref="searchRef"
    v-model:form="searchForm"
    v-model:loading="loading"
    class="nv-search"
    :option="searchOption"
    @submit="emits('search')"
  >
    <template v-for="name in searchSlotFieldNames" #[`${name}_form`]="slotData">
      <slot :name="`${name}_search`" v-bind="slotData || {}" />
    </template>

    <template #nv_search_actions_form="{ gridOverflow, gridResponsiveRows }">
      <Teleport
        defer
        :disabled="!actions.teleportTo"
        :to="actions.teleportTo"
      >
        <NFlex align="center" class="nv-search-actions">
          <slot name="search_actions_pre" :overflow="gridOverflow" />
          <NvButton
            v-if="resolveVisible(actions.searchBtn, true)"
            :content="t.button.search"
            type="primary"
            attr-type="submit"
            :on-click="expose.search"
            v-bind="resolveBind(actions.searchBtn)"
            :default-render-icon="() => h(Search24Filled)"
            :loading
          />
          <NvButton
            v-if="resolveVisible(actions.clearBtn, true)"
            :disabled="loading"
            :content="t.button.clear"
            :on-click="expose.clear"
            v-bind="resolveBind(actions.clearBtn)"
            :default-render-icon="() => h(Dismiss24Filled)"
          />
          <template v-if="actions.collapseBtn !== false">
            <NvButton
              v-if="collapseVisible(gridResponsiveRows)"
              text
              type="primary"
              :on-click="expose.toggleCollapse"
              v-bind="resolveBind(actions.collapseBtn)"
              :default-render-icon="() => h(ChevronDown24Filled, { style: collapsed ? '' : 'transform: rotate(180deg)' })"
              :content="collapseContent"
            />
          </template>
          <slot name="search_actions" :overflow="gridOverflow" />
        </NFlex>
      </Teleport>
    </template>
  </NvForm>
</template>

<script setup lang="ts">
import type { Emits, Expose, Props } from './types'
import type { NvFormInst } from '@/form/types'
import type { RowData } from '@/types'
import { ChevronDown24Filled, Dismiss24Filled, Search24Filled } from '@vicons/fluent'
import { NFlex } from 'naive-ui'
import { computed, h, ref } from 'vue'
import { NvButton } from '@/components'
import NvForm from '@/form/Index.vue'
import { resolveBind, resolveVisible } from '@/utils'
import { useLocale } from '@/utils/locale'
import { useCollapse } from './use-collapse'
import { useSearchOption } from './use-search'

const props = defineProps<Props>()
const emits = defineEmits<Emits>()
const slots = defineSlots()

const searchForm = defineModel<RowData>('searchForm', { required: true })
const loading = defineModel<boolean>('loading', { required: true })

const searchSlotFieldNames = computed(() => {
  const names: string[] = []
  for (const name in slots) {
    if (name.endsWith('_search')) {
      names.push(name.slice(0, -7))
    }
  }
  return names
})

const t = useLocale()

const searchRef = ref<NvFormInst>()

const { originalSearchOption, searchOption } = useSearchOption(props)

const actions = computed(() => {
  const _actions = originalSearchOption.value.actions
  return typeof _actions === 'object' ? _actions : {}
})

const { collapsed, collapseVisible, collapseContent } = useCollapse(searchOption, originalSearchOption, actions, t)

const expose = {
  search: () => searchRef.value?.submit(),
  clear: () => searchRef.value?.clear(),
  toggleCollapse: () => { collapsed.value = !collapsed.value },
  validate: ((...args) => searchRef.value!.validate(...args)) as NvFormInst['validate'],
  restoreValidation: () => searchRef.value!.restoreValidation(),
}
defineExpose<Expose>(expose)
</script>

<style lang="scss">
.nv-search {
  flex-grow: 1;

  .n-form-item.n-form-item--left-labelled {
    margin-top: 15px;
  }
}
.nv-search-actions {
  width: 100%;
}
</style>
